Jetson Xavier NXでRealSenseを使用する際のインストール方法・注意点・実装コード(2台編)
カフェチームの山本です。
現在、カフェではコンピュータビジョン用のカメラとして、Intel製のRealSenseというデバイスを利用し、RGB画像とDepth画像を取得しています。
(8/17:タイトルを「複数台編」から「2台編」に変更しました。)
前回は、RealSenseデバイスを1台のみ利用する場合でしたが、今回は2台利用する場合について記載します。
0.Jetson Xavier NXを準備
前回の記事をご覧ください。
1.RealSense用ライブラリをインストール
前回の記事をご覧ください。
2.接続する場合の問題点と解決法
問題点:2つ目のRealSenseデバイスに接続できない
前回の記事で実装したコードを元に、以下のようなコードを実装しました。
import pyrealsense2 as rs import usb import numpy as np import cv2 import time ID_VENDOR_REALSENSE = 0x8086 # Intel MANUFACTURER_REALSENSE = "Intel(R) RealSense(TM)" PRODUCT_REALSENSE = "Intel(R) RealSense(TM)" CAPTURE_WIDTH = 640 CAPTURE_HEIGHT = 480 CAPTURE_FPS = 60 def reset_realsense_devices(): usb_devices = usb.core.find(find_all=True) def is_realsense_device(dev): is_same_idVendor = dev.idVendor == ID_VENDOR_REALSENSE if not is_same_idVendor: return False is_same_manufacturer = MANUFACTURER_REALSENSE in dev.manufacturer is_same_product = PRODUCT_REALSENSE in dev.product return is_same_manufacturer and is_same_product realsense_devices = filter(is_realsense_device, usb_devices) for dev in realsense_devices: dev.reset() def get_realsense_serialnumbers(max_n=1): # pyrealsense2.context ctx = rs.context() # pyrealsense2.device_list devices = ctx.query_devices() serial_numbers = map(lambda device: device.get_info(rs.camera_info.serial_number), devices) serial_numbers_ = list(serial_numbers)[:max_n] return serial_numbers_ def setup_realsense_camera(device_serial_number, width, height, fps): # ストリーム(Color/Depth)の設定 config = rs.config() config.enable_device(device_serial_number) config.enable_stream(rs.stream.color, width, height, rs.format.bgr8, fps) config.enable_stream(rs.stream.depth, width, height, rs.format.z16, fps) # ストリーミング開始 pipeline = rs.pipeline() profile = pipeline.start(config) return pipeline, profile def get_images(pipeline): frames = pipeline.wait_for_frames() # RGB RGB_frame = frames.get_color_frame() RGB_image = np.asanyarray(RGB_frame.get_data()) # depth depth_frame = frames.get_depth_frame() depth_image = np.asanyarray(depth_frame.get_data()) return RGB_image, depth_image def main(): # reset usb connection of realsense devices print("reset_realsense_devices") while True: try: reset_realsense_devices() break except: print("Exception in reset_realsense_devices") print("try again in 1 second") import traceback traceback.print_exc() print() time.sleep(1) continue # setup pipeline print("get_realsense_serialnumbers") while True: serial_numbers = get_realsense_serialnumbers(max_n=2) if len(serial_numbers) > 0: break else: print("failed to get realsense serial number") print("try again in 1 second") time.sleep(1) continue print(serial_numbers) print("setup_realsense_camera") pipelines = [] for serial_number in serial_numbers: pipeline, _ = setup_realsense_camera(serial_number, CAPTURE_WIDTH, CAPTURE_HEIGHT, CAPTURE_FPS) pipelines.append(pipeline) # get image and show print("get_images") i = 0 while True: # print(i) RGB_images = [] for pipeline in pipelines: RGB_image, depth_image = get_images(pipeline) RGB_images.append(RGB_image) # depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.08), cv2.COLORMAP_JET) for j, RGB_image in enumerate(RGB_images): cv2.imshow(f"realsense image {j}", RGB_image) key = cv2.waitKey(1) if key == 27: # ESC break i += 1 if __name__ == "__main__": main()
このプログラムを実行すると、setup_realsense_cameraで2つ目のRealSenseデバイスに接続する際に、65行目のprofile = pipeline.start(config)で処理止まり関数から帰って来ない、という問題が発生しました(ターミナルでctrl+cを入力しても止まらず、ctrl+zを入力すると止まります)。プログラムを何度実行したり、OSを再起動したり、RealSenseデバイスを接続し直しても同様の結果でした。
解決策:設定する順序を変更する
色々試した結果、RealSenseデバイスに接続する順番を変えるとうまくいくことがわかりました。
3.実装したコード
上のコードとほとんど同じですが、110行目を変更しています。get_realsense_serialnumbersで取得したシリアル番号を、逆順に取り出してsetup_realsense_cameraで接続することで、処理が止まらず動作させることができました。プログラムを再実行、OS再起動、RealSenseデバイスを接続し直しても、動作しました。
確認したのは2台までの場合で、3台以上の場合はこの方法では動作しない可能性があります。ご注意ください。
import pyrealsense2 as rs import usb import numpy as np import cv2 import time ID_VENDOR_REALSENSE = 0x8086 # Intel MANUFACTURER_REALSENSE = "Intel(R) RealSense(TM)" PRODUCT_REALSENSE = "Intel(R) RealSense(TM)" CAPTURE_WIDTH = 640 CAPTURE_HEIGHT = 480 CAPTURE_FPS = 60 def reset_realsense_devices(): usb_devices = usb.core.find(find_all=True) def is_realsense_device(dev): is_same_idVendor = dev.idVendor == ID_VENDOR_REALSENSE if not is_same_idVendor: return False is_same_manufacturer = MANUFACTURER_REALSENSE in dev.manufacturer is_same_product = PRODUCT_REALSENSE in dev.product return is_same_manufacturer and is_same_product realsense_devices = filter(is_realsense_device, usb_devices) for dev in realsense_devices: dev.reset() def get_realsense_serialnumbers(max_n=1): # pyrealsense2.context ctx = rs.context() # pyrealsense2.device_list devices = ctx.query_devices() serial_numbers = map(lambda device: device.get_info(rs.camera_info.serial_number), devices) serial_numbers_ = list(serial_numbers)[:max_n] return serial_numbers_ def setup_realsense_camera(device_serial_number, width, height, fps): # ストリーム(Color/Depth)の設定 config = rs.config() config.enable_device(device_serial_number) config.enable_stream(rs.stream.color, width, height, rs.format.bgr8, fps) config.enable_stream(rs.stream.depth, width, height, rs.format.z16, fps) # ストリーミング開始 pipeline = rs.pipeline() profile = pipeline.start(config) return pipeline, profile def get_images(pipeline): frames = pipeline.wait_for_frames() # RGB RGB_frame = frames.get_color_frame() RGB_image = np.asanyarray(RGB_frame.get_data()) # depth depth_frame = frames.get_depth_frame() depth_image = np.asanyarray(depth_frame.get_data()) return RGB_image, depth_image def main(): # reset usb connection of realsense devices print("reset_realsense_devices") while True: try: reset_realsense_devices() break except: print("Exception in reset_realsense_devices") print("try again in 1 second") import traceback traceback.print_exc() print() time.sleep(1) continue # setup pipeline print("get_realsense_serialnumbers") while True: serial_numbers = get_realsense_serialnumbers(max_n=2) if len(serial_numbers) > 0: break else: print("failed to get realsense serial number") print("try again in 1 second") time.sleep(1) continue print(serial_numbers) print("setup_realsense_camera") pipelines = [] for serial_number in reversed(serial_numbers): pipeline, _ = setup_realsense_camera(serial_number, CAPTURE_WIDTH, CAPTURE_HEIGHT, CAPTURE_FPS) pipelines.append(pipeline) # get image and show print("get_images") i = 0 while True: # print(i) RGB_images = [] for pipeline in pipelines: RGB_image, depth_image = get_images(pipeline) RGB_images.append(RGB_image) # depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.08), cv2.COLORMAP_JET) for j, RGB_image in enumerate(RGB_images): cv2.imshow(f"realsense image {j}", RGB_image) key = cv2.waitKey(1) if key == 27: # ESC break i += 1 if __name__ == "__main__": main()
まとめ
コンピュータビジョン用のカメラとして利用できるIntel製のRealSenseを、Jetson Xavier NXで動かすためのコードを実装しました。接続順をpyrealsenseから得られる順番の逆にすることで、2台接続することができました。